﻿function AzureSignature(credentials) {

    var accountName = credentials.getAccountName();
    
    function encode(str) {
        return credentials.sign(str);
    }

    function sortQueries(request) {
        var uri = request.uri;
        var queries = uri.getQueries();
        var res = [];
        for (var name in queries) {
            res.push(name);
        }
        res.sort();
        return res;
    }

    function getCanonicalizedHeaders(headers) {
        var hdrs = [];
        for (var name in headers) {
            if (name.indexOf('x-ms') == 0) {
                hdrs.push(name);
            }
        }
        hdrs.sort();
        var res = '';
        for (var i = 0; i < hdrs.length; i++) {
            var hdrName = hdrs[i];
            res += hdrName.toLowerCase() + ':' + headers[hdrName] + '\n';
        }
        return res;
    }

    function getCanonicalizedResource(request) {
        var uri = request.uri;
        var queries = uri.getQueries();
        
        var res = request.resource;
        var sorted = sortQueries(request);
        for (var i = 0; i < sorted.length; i++) {
            var name = sorted[i];
            var val = queries[name];
            res += '\n';
            res += name;
            res += ':';
            res += val[0].toString();
        }
        return res;
    }
    
    function getCanonicalizedTableResource(request) {
        var res = request.resource;
        var comp = request.query['comp'];
        if (comp) {
            res += '?comp=' + encodeURI(comp);
        }
        return res;
    }
    
    var sep = '\n';

    function getSharedKeySignature(request) {
        var headers = request.headers;
        var resource = getCanonicalizedResource(request);

        var contentEncoding = headers['Content-Encoding'];
        var contentLanguage = headers['Content-Language'];
        var contentLength = headers['Content-Length'];
        var contentMd5 = headers['Content-MD5'];
        var contentType = headers['Content-Type'];

        var date = headers['Date'];

        var ifModifiedSince = headers['If-Modified-Since'];
        var ifMatch = headers['If-Match'];
        var ifNonMatch = headers['If-None-Match'];
        var ifUnmodifiedMatchSince = headers['If-Unmodified-Since'];
        var range = headers['Range'];

        var canonicalizedHeaders = getCanonicalizedHeaders(headers);

        var sign = request.verb + sep;
        sign += (contentEncoding || '') + sep;
        sign += (contentLanguage || '') + sep;
        sign += (contentLength || '') + sep;
        sign += (contentMd5 || '') + sep;
        sign += (contentType || '') + sep;
        sign += (date || '') + sep;
        sign += (ifModifiedSince || '') + sep;
        sign += (ifMatch || '') + sep;
        sign += (ifNonMatch || '') + sep;
        sign += (ifUnmodifiedMatchSince || '') + sep;
        sign += (range || '') + sep;
        sign += canonicalizedHeaders + resource;
        return sign;
    }

    function getSharedKeyLiteSignature(request) {
        var headers = request.headers;
        var resource = getCanonicalizedResource(request);

        var contentMd5 = headers['Content-MD5'];
        var contentType = headers['Content-Type'];

        var date = headers['Date'];

        var canonicalizedHeaders = getCanonicalizedHeaders(headers);

        var sign = request.verb + sep;
        sign += (contentMd5 || '') + sep;
        sign += (contentType || '') + sep;
        sign += (date || '') + sep;
        sign += canonicalizedHeaders + resource;
        return sign;
    }
    
    function getSharedKeyTablesSignature(request) {
        var headers = request.headers;
        var resource = getCanonicalizedTableResource(request);

        var contentMd5 = headers['Content-MD5'];
        var contentType = headers['Content-Type'];

        var date = headers['Date'];

        var sign = request.verb + sep;
        sign += (contentMd5 || '') + sep;
        sign += (contentType || '') + sep;
        sign += (date || '') + sep;
        sign += resource;
        return sign;
    }

    function getSharedKeyLiteTablesSignature(request) {
        var headers = request.headers;
        var resource = getCanonicalizedTableResource(request);

        var date = headers['Date'];

        var sign = '';
        sign += (date || '') + sep;
        sign += resource;
        return sign;
    }

    function signRequest(type, request) {
        request.headers.Authorization = type + ' ' + accountName + ':' + encode(request.stringToSign);
    }
    
    this.signTablesRequest = function (request) {
        request.stringToSign = getSharedKeyTablesSignature(request);
        signRequest('SharedKey', request);
    };
    this.signTablesLiteRequest = function (request) {
        request.stringToSign = getSharedKeyLiteTablesSignature(request);
        signRequest('SharedKeyLite', request);
    };
    this.signBlobsRequest = function (request) {
        request.stringToSign = getSharedKeySignature(request);
        signRequest('SharedKey', request);
    };
    this.signQueuesRequest = function (request) {
        request.stringToSign = getSharedKeySignature(request);
        signRequest('SharedKey', request);
    };
    this.getSharedKeySignature = getSharedKeySignature;
    this.getSharedKeyTablesSignature = getSharedKeyTablesSignature;
    this.getSharedKeyLiteSignature = getSharedKeyLiteSignature;
    this.getSharedKeyLiteTablesSignature = getSharedKeyLiteTablesSignature;
}

